const fs = require('fs');
const ivm = require('isolated-vm');
const Redis = require('ioredis');
const { Sequelize, DataTypes } = require('sequelize');

// 定义抽象类 DataAdapter
class DataAdapter {
  async load() {
    throw new Error('Method not implemented.');
  }

  parse(data) {
    throw new Error('Method not implemented.');
  }

  async exec(script, data) {
    throw new Error('Method not implemented.');
  }
}

// Redis 适配器实现
class RedisAdapter extends DataAdapter {
  constructor(redisOptions) {
    super();
    this.redis = new Redis(redisOptions);
  }

  async load(key) {
    return await this.redis.get(key);
  }

  parse(data) {
    return JSON.parse(data);
  }

  async exec(script, data) {
    const isolate = new ivm.Isolate({ memoryLimit: 128 });
    const context = await isolate.createContext();
    const jail = context.global;
    await jail.set('global', jail.derefInto());
    await jail.set('_ivm', ivm);
    await jail.set('data', new ivm.ExternalCopy(data).copyInto());

    const scriptExecution = await isolate.compileScript(script);
    const promise = scriptExecution.run(context);

    // Set a timer to limit script execution time
    const timeout = new Promise((_, reject) =>
      setTimeout(() => reject(new Error('Script execution timed out.')), 1000)
    );

    return Promise.race([promise, timeout]);
  }
}

// File 适配器实现
class FileAdapter extends DataAdapter {
  constructor(filePath) {
    super();
    this.filePath = filePath;
  }

  async load() {
    return fs.promises.readFile(this.filePath, 'utf8');
  }

  parse(data) {
    return JSON.parse(data);
  }

  async exec(script, data) {
    // Similar to RedisAdapter
  }
}

// RDS 适配器实现
class RDSAdapter extends DataAdapter {
  constructor(sequelizeOptions) {
    super();
    this.sequelize = new Sequelize(sequelizeOptions);
    this.Script = this.sequelize.define('Script', {
      code: {
        type: DataTypes.TEXT,
        allowNull: false
      }
    });
  }

  async load(id) {
    const script = await this.Script.findByPk(id);
    return script ? script.code : null;
  }

  parse(data) {
    return JSON.parse(data);
  }

  async exec(script, data) {
    // Similar to RedisAdapter
  }
}

// 使用示例
async function runScript(adapter, key, data) {
  try {
    const scriptString = await adapter.load(key);
    const parsedData = adapter.parse(data);
    const result = await adapter.exec(scriptString, parsedData);
    return result;
  } catch (error) {
    console.error(error);
    return { error: '执行脚本出错或超时' };
  }
}

// 假设我们已经获得了适配器实例 adapter
// const adapter = new RedisAdapter({ ... });
// const scriptKey = 'some_script_key';
// const requestData = { ... };

// runScript(adapter, scriptKey, requestData).then(result => {
//   console.log(result);
// });

